#ifndef __SD__
#define __SD__

/* COMMANDs */
#define CMD0    0x40 | 0
#define CMD1    0x40 | 1
#define CMD9    0x40 | 9
#define CMD10   0x40 | 10
#define CMD16   0x40 | 16
#define CMD17   0x40 | 17
#define CMD24   0x40 | 24
#define CMD55   0x40 | 55
#define ACMD41  0x40 | 41

#define SEND_CSD	CMD9
#define SEND_CID	CMD10
#define SET_BLK_LEN	CMD16


typedef struct _typSdCID {
	uint8_t	MIB;
	uint8_t OID[2];
	uint8_t PNM[5];
	uint8_t PRV;
	uint16_t MDR:12,
			 RSV1:4;
	uint8_t	RSV2:1,
			CRC7:7;
}_typSdCID;

typedef struct _typSdCSD {
	union {
		uint32_t ints[4];
		uint8_t	bytes[16];
	} raw;
} _typSdCSD;

#define C_SIZE(x) ((((uint16_t)x[6] & 0x0003) << 10) | (((uint16_t)x[7] & 0x00FF) << 2) | (((uint16_t)x[8]& 0x00C0) >> 6))
//#define C_SIZE(x) ((uint16_t)(((x[6] & 0x03) << 2) | (x[7] >> 6)) << 8) | (x[7] << 2) | (x[8] >> 6)
#define C_SIZE_MULT(x) pow(2,(((x[9] & 0x03) << 1) | (x[10] >> 7))+2)
#define SD_SECTORS(x) ((uint32_t)C_SIZE(x)+1) * (uint32_t)C_SIZE_MULT(x)
#define SD_SIZE(x)		SD_SECTORS(x) * 512

uint8_t SDInit(void);
uint8_t SDRead(uint8_t *buffer, uint8_t length);
void	SDCmd(uint8_t cmd, unsigned long param);
uint8_t SDGetCID(_typSdCID *data);
uint8_t SDWait(void);
uint32_t SDGetSize(void);
uint8_t SDReadFromSector(uint32_t sector, uint8_t *sdbuff, uint32_t length, uint16_t offset);
uint8_t SDWriteFromSector(uint32_t sector, uint8_t *sdbuff, uint16_t length, uint8_t *sdbuff2, uint16_t length2);
#endif
